<template>
  <div>
    <h3>组件的生命周期</h3>
    <div class="wrapper">
      <input type="text" v-model="message" >
      <p>
        <span>{{ message }}</span> 
        <span>({{length}})</span>
      </p>
      <button @click="handler">点我试试</button>
    </div>
    <div class="wrapper">
      <router-link to="/book">图书</router-link>
      |
      <router-link to="/course">课程</router-link>
      <router-view></router-view>
    </div>
    <div class="wrapper">
      <a @click="currentName = 'email'" class="sign">用邮箱登录</a>
      <a @click="currentName = 'tel'" class="sign">用手机号登录</a>
      <keep-alive>
          <component v-bind:is="currentName"></component>
      </keep-alive>
    </div>
  </div>
</template>

<script>
import Email from '@/components/Email.vue' ;
import Tel from '@/components/Tel.vue' ;

export default {
  name: 'App',
  // 局部注册
  components: {
    'email': Email ,
    'tel': Tel
  },
  // Data Property
  data(){
    return {
      message: '测试根组件的生命周期' ,
      currentName: 'tel'
    }
  },
  // 方法
  methods: {
    handler( { target } ){
      console.log( target );
      this.message = 'hello,component.' ;
    }
  },
  // 计算属性
  computed: {
    length(){
      return this.message.length ;
    }
  },
  // 生命周期钩子: 
  // beforeCreate 在实例初始化后，进行数据侦听、事件与侦听器的配置之前同步调用
  beforeCreate(){
    console.log( '- - - beforeCreate - - -' );
    console.log( '\tmessage ( data property ): ' , this.message );
    console.log( '\tlength ( computed property ): ' , this.length );
    console.log( '\thandler ( methods ): ' , this.handler );
  },
  // 生命周期钩子: 
  // created 在 在实例创建完成后被立即同步调用，此时实例已完成对选项的处理
  created(){
    console.log( '- - - created - - -' );
    console.log( '\tmessage ( data property ): ' , this.message );
    console.log( '\tlength ( computed property ): ' , this.length );
    console.log( '\thandler ( methods ): ' , this.handler );
    console.log( '\t' , this );
  },
  // 生命周期钩子
  // beforeMount 在挂载开始之前被调用：相关的 render 函数首次被调用
  beforeMount(){
    console.log( '- - - beforeMount - - -' );
    console.log( `\t在此之前已经完成对模板(template)的编译，此时需要完成渲染(render)操作` );
    console.log( `\t$el: ${this.$el}`);
    console.log( '\tbutton: ' , document.querySelector( 'button' ) );
  },
  // 生命周期钩子
  // mounted 在实例挂载完成后被调用
  mounted(){
    console.log( '- - - mounted - - -' );
    console.log( `\t此时已经完成组件的挂载` );
    // 此时传递给 app.mount 的元素已经被新创建的 vm.$el 替换了
    console.log( `\t$el: ` , this.$el );
    // 若根实例被挂载到了一个文档内的元素上，则 vm.$el 也会在文档内
    console.log( '\tbutton: ' , document.querySelector( 'button' ) );
  },
  // 生命周期钩子
  // beforeUpdate 在数据发生改变后，DOM 被更新之前被调用
  beforeUpdate(){
    console.log( '- - - beforeUpdate - - -' );
    console.log( `\tmessage ( data property ) : ${this.message}` );
    console.log( `\tmessage ( DOM ) : ${document.querySelector('p>span:first-child').innerHTML}` );
  },
  // 生命周期钩子
  // updated 在数据更改导致的虚拟 DOM 重新渲染和更新完毕之后被调用
  updated(){
    console.log( '- - - updated - - -' );
    console.log( `\tmessage ( data property ) : ${this.message}` );
    console.log( `\tmessage ( DOM ) : ${document.querySelector('p>span:first-child').innerHTML}` );
  },
  // 生命周期钩子
  // beforeUnmount 在卸载组件实例之前调用
  beforeUnmount(){
    console.log( '- - - beforeUnmount - - -' );
    // 在这个阶段，实例仍然是完全正常的
    console.log( `\tmessage ( data property ) : ${this.message}` );
    // 使用原生 JavaScript 获取 DOM 元素
    let span = document.querySelector('p>span:first-child') ;
    console.log( `\tmessage ( DOM ) : ${ span ? span.innerHTML : '' }` );
  },
  // 生命周期钩子
  // unmounted 卸载组件实例后调用
  unmounted(){
    console.log( '- - - unmounted - - -' );
    console.log( `\tmessage ( data property ) : ${this.message}` );
    let span = document.querySelector('p>span:first-child') ;
    console.log( `\tmessage ( DOM ) : ${ span ? span.innerHTML : '' }` );
  }
}
</script>

<style>
.wrapper {
  border: 1px solid blue ;
  margin: 15px auto ;
  padding: 15px ;
}

.sign {
  display: inline-block ;
  margin: 5px;
  margin-left: 0 ;
  border: 1px solid blue ;
  padding: 5px ;
  background: rgb(93, 93, 255) ;
  color: #fff;
  cursor: pointer;
  user-select: none ;
}
</style>
